package fr.gdi.android.news.widgets;

import java.io.File;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.GregorianCalendar;

import mobi.intuitit.android.content.LauncherIntent;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PathEffect;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.graphics.drawable.PaintDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.graphics.drawable.shapes.RoundRectShape;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RemoteViews;
import fr.gdi.android.news.ConfigurationActivity;
import fr.gdi.android.news.NewsProvider;
import fr.gdi.android.news.R;
import fr.gdi.android.news.ReadMoreActivity;
import fr.gdi.android.news.SimpleNewsEntry;
import fr.gdi.android.news.UpdateService;
import fr.gdi.android.news.utils.Constants;
import fr.gdi.android.news.utils.Constants.Actions;
import fr.gdi.android.news.utils.Constants.Configuration;
import fr.gdi.android.news.utils.Constants.Preferences;
import fr.gdi.android.news.utils.Constants.Provider;
import fr.gdi.android.news.utils.Constants.URI;
import fr.gdi.android.news.utils.PreferenceUtils;
import fr.gdi.android.news.utils.Utils;

public abstract class ScrollableNewsWidget extends AppWidgetProvider
{
    
    @Override
    public void onReceive(Context context, Intent intent)
    {
        final String action = intent.getAction();
        
        if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action))
        {
            final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID)
            {
                this.onDeleted(context, new int[] { appWidgetId });
            }
        }
        else if (TextUtils.equals(action, LauncherIntent.Action.ACTION_READY))
        {
            onAppWidgetReady(context, intent);
        }
        else if (TextUtils.equals(action, LauncherIntent.Action.ACTION_FINISH))
        {
            
        }
        else if (TextUtils.equals(action, LauncherIntent.Action.ACTION_ITEM_CLICK))
        {
            onClick(context, intent);
        }
        else if (TextUtils.equals(action, LauncherIntent.Action.ACTION_VIEW_CLICK))
        {
            onClick(context, intent);
        }
        else if (TextUtils.equals(action, LauncherIntent.Error.ERROR_SCROLL_CURSOR))
        {
            // swallow
        }
        else if (TextUtils.equals(action, android.net.ConnectivityManager.CONNECTIVITY_ACTION))
        {
            // onUpdate(context, AppWidgetManager.getInstance(context),
            // Utils.getAllWidgetIds(context));
        }
        else if (TextUtils.equals(Actions.ACTION_NOTIFY_LOADING, action))
        {
            final int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
            if ((appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) && appWidgetClassMatch(context, appWidgetId))
            {
                update(context, appWidgetId, intent.getExtras().getBoolean("loading"), intent.getExtras().getBoolean("downloading"));
            }
        }
        else
        {
            super.onReceive(context, intent);
        }
    }
    
    public void onEnabled(Context context)
    {
        if (UpdateService.serviceIntent == null)
        {
            UpdateService.register(context);
        }
    }
    
    public void onAppWidgetReady(Context context, Intent intent)
    {
        if (intent == null) return;
        
        int appWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
        
        if (appWidgetId < 0)
        {
            return;
        }
        
        redraw(context, appWidgetId);
    }
    
    /*
     * public static void redraw(Context context, int appWidgetId) { String
     * widgetUri =
     * URI.CONTENT_URI_WIDGET_FEEDS.buildUpon().appendEncodedPath(Integer
     * .toString(appWidgetId)).toString();
     * 
     * Intent clearIntent = new
     * Intent(LauncherIntent.Action.ACTION_SCROLL_WIDGET_CLOSE);
     * clearIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
     * clearIntent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI,
     * widgetUri); context.sendBroadcast(clearIntent);
     * 
     * Intent replaceDummy = new
     * Intent(LauncherIntent.Action.ACTION_SCROLL_WIDGET_START);
     * 
     * replaceDummy.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
     * replaceDummy.putExtra(LauncherIntent.Extra.EXTRA_VIEW_ID,
     * R.id.content_view);replaceDummy.putExtra(LauncherIntent.Extra.Scroll.
     * EXTRA_DATA_PROVIDER_ALLOW_REQUERY, true);
     * 
     * SimpleRemoteViews gridViews = new
     * SimpleRemoteViews(R.layout.news_widget_list);
     * replaceDummy.putExtra(LauncherIntent
     * .Extra.Scroll.EXTRA_LISTVIEW_REMOTEVIEWS, gridViews);
     * 
     * BoundRemoteViews itemViews = new
     * BoundRemoteViews(R.layout.news_widget_list_item_full);
     * itemViews.setBoundCharSequence(R.id.title, "setText",
     * Provider.Columns.NEWS_TITLE.ordinal(), 0);
     * itemViews.setBoundCharSequence(R.id.author, "setText",
     * Provider.Columns.NEWS_AUTHOR.ordinal(), 0);
     * itemViews.setBoundCharSequence(R.id.link, "setText",
     * Provider.Columns.NEWS_LINK.ordinal(), 0);
     * itemViews.setBoundCharSequence(R.id.date, "setText",
     * Provider.Columns.NEWS_DATE.ordinal(), 0);
     * itemViews.setBoundCharSequence(R.id.description, "setText",
     * Provider.Columns.NEWS_DESCRIPTION.ordinal(), 0);
     * itemViews.setBoundBitmap(R.id.thumbnail, "setImageBitmap",
     * Provider.Columns.NEWS_IMAGE_URL.ordinal(), 0);
     * 
     * itemViews.setTextColor(R.id.title,
     * PreferenceUtils.getIntPreference(context, Preferences.HEADLINE_COLOR,
     * Color.WHITE, appWidgetId)); itemViews.setTextColor(R.id.author,
     * PreferenceUtils.getIntPreference(context, Preferences.FOOTER_COLOR,
     * Color.WHITE, appWidgetId)); itemViews.setTextColor(R.id.date,
     * PreferenceUtils.getIntPreference(context, Preferences.FOOTER_COLOR,
     * Color.WHITE, appWidgetId)); itemViews.setTextColor(R.id.description,
     * PreferenceUtils.getIntPreference(context, Preferences.SUMMARY_COLOR,
     * Color.WHITE, appWidgetId)); itemViews.setViewVisibility(R.id.description,
     * PreferenceUtils.getCropLength(context, appWidgetId) >= 0 ? View.VISIBLE :
     * View.GONE);
     * 
     * boolean hideFooter = PreferenceUtils.getBooleanPreference(context,
     * Preferences.HIDE_FOOTER, appWidgetId);
     * itemViews.setViewVisibility(R.id.date, hideFooter ? View.GONE :
     * View.VISIBLE); itemViews.setViewVisibility(R.id.author, hideFooter ?
     * View.GONE : View.VISIBLE);
     * 
     * Intent intent = new Intent(context, getWidgetClass(context,
     * appWidgetId)); intent.setAction(LauncherIntent.Action.ACTION_VIEW_CLICK);
     * intent.setData(Uri.parse(widgetUri));
     * intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
     * PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
     * intent, 0);
     * 
     * itemViews.SetBoundOnClickIntent(R.id.title, pendingIntent,
     * LauncherIntent.Extra.Scroll.EXTRA_ITEM_POS,
     * Provider.Columns.NEWS_LINK.ordinal());
     * itemViews.SetBoundOnClickIntent(R.id.description, pendingIntent,
     * LauncherIntent.Extra.Scroll.EXTRA_ITEM_POS,
     * Provider.Columns.NEWS_LINK.ordinal());
     * itemViews.SetBoundOnClickIntent(R.id.author, pendingIntent,
     * LauncherIntent.Extra.Scroll.EXTRA_ITEM_POS,
     * Provider.Columns.NEWS_LINK.ordinal());
     * itemViews.SetBoundOnClickIntent(R.id.date, pendingIntent,
     * LauncherIntent.Extra.Scroll.EXTRA_ITEM_POS,
     * Provider.Columns.NEWS_LINK.ordinal());
     * 
     * replaceDummy.putExtra(LauncherIntent.Extra.Scroll.
     * EXTRA_ITEM_LAYOUT_REMOTEVIEWS, itemViews);
     * 
     * putProvider(replaceDummy, widgetUri);
     * replaceDummy.putExtra(LauncherIntent
     * .Extra.Scroll.EXTRA_ITEM_CHILDREN_CLICKABLE, true);
     * 
     * context.sendBroadcast(replaceDummy); }
     */
    public static void redraw(Context context, int appWidgetId)
    {
        String widgetUri = URI.CONTENT_URI_WIDGET_FEEDS.buildUpon().appendEncodedPath(Integer.toString(appWidgetId)).toString();
        
        Intent clearIntent = new Intent(LauncherIntent.Action.ACTION_SCROLL_WIDGET_CLOSE);
        clearIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        clearIntent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI, widgetUri);
        context.sendBroadcast(clearIntent);
        
        Intent replaceDummy = new Intent(LauncherIntent.Action.ACTION_SCROLL_WIDGET_START);
        
        replaceDummy.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        replaceDummy.putExtra(LauncherIntent.Extra.EXTRA_VIEW_ID, R.id.content_view);
        
        replaceDummy.putExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_PROVIDER_ALLOW_REQUERY, true);
        
        replaceDummy.putExtra(LauncherIntent.Extra.Scroll.EXTRA_LISTVIEW_LAYOUT_ID, R.layout.news_widget_list);
        
        replaceDummy.putExtra(LauncherIntent.Extra.Scroll.EXTRA_ITEM_LAYOUT_ID, R.layout.news_widget_list_item_summary_footer);
        
        int layoutId = getLayoutId(context, appWidgetId);
        
        replaceDummy.putExtra(LauncherIntent.Extra.Scroll.EXTRA_ITEM_LAYOUT_ID, layoutId);
        replaceDummy.putExtra(LauncherIntent.Extra.Scroll.EXTRA_ITEM_CHILDREN_CLICKABLE, true);
        
        putProvider(replaceDummy, widgetUri);
        putMapping(replaceDummy);
        
        context.sendBroadcast(replaceDummy);
    }

    private static int getLayoutId(Context context, int appWidgetId)
    {
        boolean hideFooter = PreferenceUtils.getBooleanPreference(context, Preferences.HIDE_FOOTER, appWidgetId);
        boolean showImages = PreferenceUtils.getBooleanPreference(context, Preferences.SHOW_IMAGES, appWidgetId);
        if (PreferenceUtils.getCropLength(context, appWidgetId) >= 0)
        {
            boolean thumbAtRight = PreferenceUtils.getBooleanPreference(context, Preferences.THUMBNAIL_AT_RIGHT, appWidgetId);
            if (hideFooter)
            {
                if ( !showImages ) return R.layout.news_widget_list_item_summary_no_footer_no_thumb;
                return thumbAtRight ? R.layout.news_widget_list_item_summary_no_footer_right : R.layout.news_widget_list_item_summary_no_footer;
            }
            else
            {
                if ( !showImages ) return R.layout.news_widget_list_item_summary_footer_no_thumb;
                return thumbAtRight ? R.layout.news_widget_list_item_summary_footer_right : R.layout.news_widget_list_item_summary_footer;
            }
        }
        else
        {
            boolean fullWidth = PreferenceUtils.getBooleanPreference(context, Preferences.FULL_WIDTH_THUMB, appWidgetId);
            if (hideFooter)
            {
                return !showImages ? R.layout.news_widget_list_item_no_summary_no_footer_no_thumb : 
                        (fullWidth ? R.layout.news_widget_list_item_no_summary_no_footer : R.layout.news_widget_list_item_no_summary_no_footer_inside);
            }
            else
            {
                return !showImages ? R.layout.news_widget_list_item_no_summary_footer_no_thumb : 
                        (fullWidth ? R.layout.news_widget_list_item_no_summary_footer : R.layout.news_widget_list_item_no_summary_footer_inside);
            }
        }
    }
    
    private static void putMapping(Intent intent)
    {
        if (intent == null) return;
        
        final int NB_ITEMS_TO_FILL = 7;
        
        int[] cursorIndices = new int[NB_ITEMS_TO_FILL];
        int[] viewTypes = new int[NB_ITEMS_TO_FILL];
        int[] layoutIds = new int[NB_ITEMS_TO_FILL];
        boolean[] clickable = new boolean[NB_ITEMS_TO_FILL];
        
        int iItem = 0;
        
        intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_ITEM_ACTION_VIEW_URI_INDEX, Provider.Columns.NEWS_LINK.ordinal());
        
        cursorIndices[iItem] = Provider.Columns.NEWS_LINK.ordinal();
        viewTypes[iItem] = LauncherIntent.Extra.Scroll.Types.TEXTVIEW;
        layoutIds[iItem] = R.id.link;
        clickable[iItem] = true;
        
        iItem++;
        
        cursorIndices[iItem] = Provider.Columns.NEWS_TITLE.ordinal();
        viewTypes[iItem] = LauncherIntent.Extra.Scroll.Types.TEXTVIEWHTML;
        layoutIds[iItem] = R.id.title;
        clickable[iItem] = true;
        
        iItem++;
        
        cursorIndices[iItem] = Provider.Columns.NEWS_DATE.ordinal();
        viewTypes[iItem] = LauncherIntent.Extra.Scroll.Types.TEXTVIEWHTML;
        layoutIds[iItem] = R.id.date;
        clickable[iItem] = true;
        
        iItem++;
        
        cursorIndices[iItem] = Provider.Columns.NEWS_DESCRIPTION.ordinal();
        viewTypes[iItem] = LauncherIntent.Extra.Scroll.Types.TEXTVIEWHTML;
        layoutIds[iItem] = R.id.description;
        clickable[iItem] = true;
        
        iItem++;
        
        cursorIndices[iItem] = Provider.Columns.NEWS_AUTHOR.ordinal();
        viewTypes[iItem] = LauncherIntent.Extra.Scroll.Types.TEXTVIEWHTML;
        layoutIds[iItem] = R.id.author;
        clickable[iItem] = true;
        
        iItem++;
        
        cursorIndices[iItem] = Provider.Columns.NEWS_IMAGE_URL.ordinal();
        viewTypes[iItem] = LauncherIntent.Extra.Scroll.Types.IMAGEBLOB;
        layoutIds[iItem] = R.id.thumbnail;
        clickable[iItem] = true;
        
        intent.putExtra(LauncherIntent.Extra.Scroll.Mapping.EXTRA_VIEW_IDS, layoutIds);
        intent.putExtra(LauncherIntent.Extra.Scroll.Mapping.EXTRA_VIEW_TYPES, viewTypes);
        intent.putExtra(LauncherIntent.Extra.Scroll.Mapping.EXTRA_VIEW_CLICKABLE, clickable);
        intent.putExtra(LauncherIntent.Extra.Scroll.Mapping.EXTRA_CURSOR_INDICES, cursorIndices);
        
    }
    
    private static void putProvider(Intent intent, String widgetUri)
    {
        if (intent == null) return;
        
        String whereClause = null;
        String orderBy = null;
        String[] selectionArgs = null;
        
        intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_DATA_URI, widgetUri);
        
        intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_PROJECTION, Provider.PROJECTION_APPWIDGETS);
        intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_SELECTION, whereClause);
        intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_SELECTION_ARGUMENTS, selectionArgs);
        intent.putExtra(LauncherIntent.Extra.Scroll.EXTRA_SORT_ORDER, orderBy);
        
    }
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
    {
        if (appWidgetIds == null || appWidgetIds.length == 0) return;
        
        for (int appWidgetId : appWidgetIds)
        {
            update(context, appWidgetId, false, false);
        }
    }
    
    private static String convert(int i)
    {
        String r = Integer.toString(i);
        if (i < 10 && i >= 0)
        {
            return "0" + r;
        }
        return r;
        
    }
    
    public static void update(Context context, int appWidgetId, Boolean loading, Boolean downloading)
    {
        String bg = PreferenceUtils.getBackground(context, appWidgetId);
        int layoutId = TextUtils.equals(bg, Configuration.NO_BACKGROUND) ? R.layout.news_widget_no_bg : R.layout.news_widget;
        
        RemoteViews views = new RemoteViews(context.getPackageName(), layoutId);
        
        if ( PreferenceUtils.getBooleanPreference(context, Preferences.HIDE_HEADER, appWidgetId) ) 
        {
            views.setViewVisibility(R.id.header, View.GONE);
            views.setViewVisibility(R.id.title_separator, View.GONE);
        }
        else 
        {
            views.setViewVisibility(R.id.header, View.VISIBLE);
            views.setViewVisibility(R.id.title_separator, View.VISIBLE);
            
            boolean offline = !Utils.isOnline(context);
            String title = PreferenceUtils.getWidgetTitle(context, appWidgetId);
            
            if (offline)
            {
                title += " " + context.getString(R.string.offline);
            }
            else
            {
                String titleFormat = PreferenceUtils.getStringPreference(context, Preferences.TITLE_FORMAT, appWidgetId);
                long lastUpdate = PreferenceUtils.getLong(context, Preferences.LAST_UPDATE + appWidgetId);
                if (lastUpdate != 0 && !TextUtils.isEmpty(titleFormat))
                {
                    boolean use12HourFormat = PreferenceUtils.getBooleanPreference(context, Preferences.USE_12_HOUR, appWidgetId);
                    GregorianCalendar cal = new GregorianCalendar();
                    cal.setLenient(true);
                    cal.setTimeInMillis(lastUpdate);
                    int month = cal.get(Calendar.MONTH);
                    DateFormatSymbols dfs = new DateFormatSymbols();
                    String monthName = dfs.getShortMonths()[month];
                    int day = cal.get(Calendar.DAY_OF_MONTH);
                    int hour = cal.get(Calendar.HOUR_OF_DAY);
                    int minutes = cal.get(Calendar.MINUTE);
                    String ampm = "";
                    if (use12HourFormat)
                    {
                        hour = cal.get(Calendar.HOUR);
                        ampm = cal.get(Calendar.AM_PM) == Calendar.AM ? "AM" : "PM";
                    }
                    title = titleFormat.replace("%t", title)
                                .replace("%M", monthName)
                                .replace("%d", Integer.toString(day))
                                .replace("%h", Integer.toString(hour))
                                .replace("%m", convert(minutes))
                                .replace("%a", ampm);
                }
            }
            
            int titleColor = PreferenceUtils.getIntPreference(context, Preferences.WIDGET_TITLE_COLOR, Color.WHITE, appWidgetId);
            views.setTextColor(R.id.widget_title_text, titleColor);
            views.setTextViewText(R.id.widget_title_text, title);
            
            Intent intent = new Intent(context, UpdateService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

            PendingIntent pendingIntent = PendingIntent.getService(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            //views.setOnClickPendingIntent(R.id.refresh_button, pendingIntent);
            views.setOnClickPendingIntent(R.id.widget_title_text, pendingIntent);
            
            intent = new Intent(context, ConfigurationActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            intent.putExtra(Constants.Configuration.LIVE_WIDGET, true);
            pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            views.setOnClickPendingIntent(R.id.feed_edit_button, pendingIntent);
        }
        
        int backgroundId = getBackgroundId(context, appWidgetId);
        views.setImageViewResource(R.id.backgroundImg, backgroundId);
        
        /*
        String backgroundUri = PreferenceUtils.getStringPreference(context, Preferences.BACKGROUND_FILE, appWidgetId);
        File background = null;
        if ( !TextUtils.isEmpty(backgroundUri) )
        {
            background = new File(backgroundUri);
        }
        
        if ( background == null || !background.exists() )
        {
            int backgroundId = getBackgroundId(context, appWidgetId);
            views.setImageViewResource(R.id.backgroundImg, backgroundId);
        }
        else
        {
            //views.setImageViewUri(R.id.backgroundImg, Uri.fromFile(new File("/sdcard/ShootMe/snap20110401_010946.png")));
            //Bitmap bmp = BitmapFactory.decodeFile(backgroundUri);
            //views.setImageViewBitmap(R.id.backgroundImg, bmp);
            views.setImageViewUri(R.id.backgroundImg, Uri.fromFile(new File(backgroundUri)));
            int alpha = PreferenceUtils.getIntPreference(context, Preferences.BACKGROUND_TRANSPARENCY, -1, appWidgetId);
            if ( alpha != -1 ) 
            {
                views.setInt(R.id.backgroundImg, "setAlpha", alpha);
                //adjustOpacity(bmp, alpha);
            }
        }
        */
        
        int loadingRes = R.id.refresh_icon;
        if (loading != null)
        {
            if (loading)
            {
                //views.setTextViewText(R.id.refresh_icon, " " + context.getString(R.string.loading));
                views.setViewVisibility(loadingRes, View.VISIBLE);
            }
            else
            {
                //views.setTextViewText(R.id.refresh_icon, "");
                views.setViewVisibility(loadingRes, View.GONE);
                Intent intent = new Intent(Constants.Actions.REFRESH_NOTIFICATION);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                context.sendBroadcast(intent);
            }
        }
        
        downloading = downloading == null || (loading != null && loading) ? false : downloading;
        
        if (downloading)
        {
            //views.setTextViewText(R.id.refresh_icon, " " + context.getString(R.string.loading));
            views.setViewVisibility(R.id.fetch_images_icon, View.VISIBLE);
        }
        else
        {
            views.setViewVisibility(R.id.fetch_images_icon, View.GONE);
        }
        
        final AppWidgetManager awm = AppWidgetManager.getInstance(context);
        awm.updateAppWidget(appWidgetId, views);
        
    }

    private static Bitmap adjustOpacity(Bitmap bitmap, int opacity)
    {
        Bitmap mutableBitmap = bitmap.isMutable()
                               ? bitmap
                               : bitmap.copy(Bitmap.Config.ARGB_8888, true);
        Canvas canvas = new Canvas(mutableBitmap);
        int colour = (opacity & 0xFF) << 24;
        canvas.drawColor(colour, Mode.DST_IN);
        return mutableBitmap;
    }
    
    private static int getBackgroundId(Context context, int appWidgetId)
    {
        String bg = PreferenceUtils.getBackground(context, appWidgetId);
        boolean square = PreferenceUtils.getBooleanPreference(context, Configuration.SQUARE_CORNERS, appWidgetId);
        int backgroundId = square ? R.drawable.square_corners : R.drawable.rounded_corners;
        if (TextUtils.equals(bg, Configuration.LIGHT))
        {
            backgroundId = square ? R.drawable.square_corners_white : R.drawable.rounded_corners_white;
        }
        
        if (TextUtils.equals(bg, Configuration.TRANSPARENT))
        {
            backgroundId = square ? R.drawable.square_corners_transparent : R.drawable.rounded_corners_transparent;
        }
        
        if (TextUtils.equals(bg, Configuration.BLACK))
        {
            backgroundId = square ? R.drawable.square_corners_black_plain : R.drawable.rounded_corners_black_plain;
        }
        
        if (TextUtils.equals(bg, Configuration.WHITE))
        {
            backgroundId = square ? R.drawable.square_corners_white_plain : R.drawable.rounded_corners_white_plain;
        }
        
        if (TextUtils.equals(bg, Configuration.NO_BACKGROUND))
        {
            backgroundId = R.drawable.transparent_drawable;
        }
        return backgroundId;
    }
    
    /*
    private static Bitmap getBackground()
    {
        float radius = 70f;
        int color = Color.RED;
        //int alpha = 128;
        float strokeWidth = 1f;

        float[] radii = new float[8];
        for (int i = 0; i < radii.length; i++)
        {
            radii[i] = radius;
        }
        
        
        final ShapeDrawable drawable = new ShapeDrawable(new RoundRectShape(radii, null, null));
        drawable.getPaint().setColor(color);
        //drawable.getPaint().setAlpha(alpha);
        drawable.getPaint().setStrokeWidth(strokeWidth);
        
        final Bitmap bitmap = Bitmap.createBitmap(368, 368, Config.ARGB_8888);
        final Canvas canvas = new Canvas(bitmap);

        canvas.drawPaint(drawable.getPaint());
        
        drawable.draw(canvas);
        
        
        canvas.setBitmap(bitmap);
        

        
        drawable.draw(canvas);

        return bitmap;
    }
    */
    
    protected boolean appWidgetClassMatch(Context context, int appWidgetId)
    {
        final AppWidgetManager awm = AppWidgetManager.getInstance(context);
        final AppWidgetProviderInfo info = awm.getAppWidgetInfo(appWidgetId);
        if (info != null)
        {
            Class<?> cls = getClass();
            ComponentName cn = new ComponentName(context, cls);
            return info.provider.equals(cn);
        }
        else
        {
            return false;
        }
    }
    
    public static int getApproximateWidth(Context context, int appWidgetId) 
    {
        int w = 294; 
        final AppWidgetManager awm = AppWidgetManager.getInstance(context);
        final AppWidgetProviderInfo info = awm.getAppWidgetInfo(appWidgetId);
        if (info != null)
        {
            String cn = info.provider.getShortClassName();
            if ( cn.startsWith(".widgets.Wide") ) w = 368;
        }
        
        return w + 60;
    }
    
    public void onDisabled(Context context)
    {
        UpdateService.removeService(context);
        Intent intent = new Intent(Actions.START_NOTIFICATION);
        context.sendBroadcast(intent);
        super.onDisabled(context);
    }
    
    public void onDeleted(Context context, int[] appWidgetIds)
    {
        PreferenceUtils.dropSettings(context, appWidgetIds);
        Intent intent = new Intent(Actions.START_NOTIFICATION);
        context.sendBroadcast(intent);
        super.onDeleted(context, appWidgetIds);
    }
    
    private void onClick(Context context, Intent intent)
    {
        String preferredAction = PreferenceUtils.getPreferredAction(context);
        
        if (!TextUtils.equals(preferredAction, Configuration.DO_NOTHING_ON_TAP))
        {
            Object pos = intent.getExtras().get(LauncherIntent.Extra.Scroll.EXTRA_ITEM_POS);
            
            if (Constants.USE_EMULATOR)
            {
                Log.d(this.getClass().getName(), "extra item pos = " + pos);
            }
            
            String url = (String) pos;
            SimpleNewsEntry cursor = NewsProvider.getNewsEntry(url);
            
            String title = cursor.title;
            ReadMoreActivity.open(context, url, title, preferredAction);
        }
    }
    
    public static void setLoading(Context context, Integer[] appWidgetIds, boolean loading)
    {
        
        setState("loading", context, appWidgetIds, loading);
    }
    
    public static void setDownloading(Context context, Integer[] appWidgetIds, boolean loading)
    {
        
        setState("downloading", context, appWidgetIds, loading);
    }
    
    private static void setState(String state, Context context, Integer[] appWidgetIds, boolean loading) 
    {
        if (appWidgetIds == null || appWidgetIds.length == 0) return;
        
        final Intent intent = new Intent(Actions.ACTION_NOTIFY_LOADING);
        intent.putExtra(state, loading);
        
        for (Integer appWidgetId : appWidgetIds)
        {
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            context.sendBroadcast(intent);
        }
    }
    
    /*
     * private static Class<?> getWidgetClass(Context context, int appWidgetId)
     * { try { final AppWidgetManager awm =
     * AppWidgetManager.getInstance(context); final AppWidgetProviderInfo info =
     * awm.getAppWidgetInfo(appWidgetId); return
     * Class.forName(info.provider.getClassName()); } catch
     * (ClassNotFoundException e) { Log.e(ScrollableNewsWidget.class.getName(),
     * "Cannot retrieve widget class", e); return null; } }
     */
}
